const clipboard = require(Editor.url('packages://console-pro/node_modules/clipboard/dist/clipboard.js'))
const axios = require(Editor.url('packages://console-pro/node_modules/axios/dist/axios.js'))
const packageJSON = require(Editor.url('packages://console-pro/package.json'))
const childProcess = require('child_process')
const path = require('path')
const fs = require('fs')
const os = require('os')


const translate = (key) => Editor.T(`${packageJSON.name}.${key}`)
var vm = null

// panel/index.js, this filename needs to match the one registered in package.json
Editor.Panel.extend({
  // css style for panel
  style: fs.readFileSync(Editor.url('packages://console-pro/static/style/default/index.css', 'utf8')),

  // html template for panel
  template: fs.readFileSync(Editor.url('packages://console-pro/static/template/default/index.html', 'utf8')),

  // element and variable binding
  $: {
    app: '#app',
    logDetail: '#log-detail'
  },

  close() {
  },

  // method executed when template and styles are successfully loaded and initialized
  ready () {
    vm = new window.Vue({
      el: this.shadowRoot,
      data() {
        return {
          openSettingsI18n: translate('openSettings'),
          clearLogI18n: translate('clearLog'),
          openLogI18n: translate('openLog'),
          searchPlaceholderI18n: translate('searchPlaceholder'),
          iconI18n: translate('icon'),
          timeI18n: translate('time'),
          typeI18n: translate('type'),
          contentI18n: translate('content'),
          copyI18n: translate('copy'),
          deleteI18n: translate('delete'),
          expandI18n: translate('expand'),
          collapseI18n: translate('collapse'),
          developI18n: translate('develop'),
          backI18n: translate('back'),

          currentPage: 'log',

          settingsImgPath: Editor.url('packages://console-pro/static/images/settings.png'),
          clearImgPath: Editor.url('packages://console-pro/static/images/clear.png'),
          openLogImgPath: Editor.url('packages://console-pro/static/images/log.png'),
          searchImgPath: Editor.url('packages://console-pro/static/images/search.png'),
          matchCaseImgPath: Editor.url('packages://console-pro/static/images/match-case.png'),
          matchWholeImgPath: Editor.url('packages://console-pro/static/images/match-whole.png'),
          matchRegImgPath: Editor.url('packages://console-pro/static/images/match-reg.png'),
          logNumImgPath: Editor.url('packages://console-pro/static/images/log-color.png'),
          infoNumImgPath: Editor.url('packages://console-pro/static/images/info-color.png'),
          warnNumImgPath: Editor.url('packages://console-pro/static/images/warn-color.png'),
          errorNumImgPath: Editor.url('packages://console-pro/static/images/error-color.png'),
          copyImgPath: Editor.url('packages://console-pro/static/images/copy.png'),
          deleteImgPath: Editor.url('packages://console-pro/static/images/delete.png'),
          expandImgPath: Editor.url('packages://console-pro/static/images/expand.png'),
          collapseImgPath: Editor.url('packages://console-pro/static/images/collapse.png'),

          isMatchCase: false,
          isMatchWhole: false,
          isMatchReg: false,
          matchCaseBtnClass: 'transparent',
          matchWholeBtnClass: 'transparent',
          matchRegBtnClass: 'transparent',

          logNum: 0,
          infoNum: 0,
          warnNum: 0,
          errorNum: 0,
          isLogTypeShown: true,
          isInfoTypeShown: true,
          isWarnTypeShown: true,
          isErrorTypeShown: true,

          currentLogDataArray: [],
          searchResultArray: [],
          keyword: '',

          isClearLogOnPreview: false,
          isCurrentItemExpanded: false,
          currentLogIndex: 0,
          isSearching: false,

          logDetailHTML: null,
          menuHTML: null
        }
      },

      created() {
        // 如果不需要更新提示，注释这行代码即可
        // this.checkUpdate()
      },

      computed: {
        currentLogDataArrayComputed() {
          return this.currentLogDataArray
        }
      },

      methods: {
        checkUpdate() {
          // 检查是否有更新
          axios.get('https://la-vie.gitee.io/console-pro2x/package.json', {headers: {'Cache-Control': 'no-cache'}})
               .then(function(response) {
                   let remoteVersion = response.data.version;
                   if (packageJSON.version != remoteVersion) {
                       Editor.warn(`[v${remoteVersion}] ${translate('updateWarn')}`);
                   }
               });
        },

        storeELements(event) {
          // v-el和v-ref都获取不到，只能通过这种方式获取先
          // 获取id为log-detail的元素
          this.logDetailHTML = event.currentTarget

          // 获取右键菜单元素
          this.menuHTML = event.currentTarget.parentElement.parentElement.getElementsByClassName('menu')[0]
        },

        back() {
          this.currentPage = 'log'
        },

        setClearOnPreview() {
          this.isClearLogOnPreview = !this.isClearLogOnPreview
        },
        
        escape(str) {
          return str.replace(/[\-\/\\\^\$\*\+\?\.\(\)\|\[\]\{\}]/g, '\\$&')
        },
        
        search(keyword) {
          // 关键词搜索
          this.keyword = keyword

          // 没有关键词则直接返回
          if (!keyword.length) {
            this.isSearching = false
            return
          }

          // 构造正则表达式
          this.isSearching = true
          this.searchResultArray = []
          let matchCaseRegPart = 'i'
          let matchWholeRegPart1 = ''
          let matchWholeRegPart2 = ''
          let regStr = keyword

          if (!this.isMatchReg) {
            regStr = this.escape(regStr)
          }

          if (this.isMatchCase) {
            matchCaseRegPart = ''
          }

          if (this.isMatchWhole) {
            matchWholeRegPart1 = '\\b'
            matchWholeRegPart2 = '\\b'
          }

          regStr = `${matchWholeRegPart1}${regStr}${matchWholeRegPart2}`
          let regExp = new RegExp(regStr, matchCaseRegPart+'g')

          // 将符合条件的日志放入searchResultArray中
          for (let i=0; i<this.currentLogDataArray.length; i++) {
            if (this.currentLogDataArray[i].message.search(regExp) > -1) {
              this.searchResultArray.push(this.currentLogDataArray[i])
            }
          }
        },

        showContextMenu(event, index) {
          // 显示右键菜单
          event.preventDefault()

          let logDetailLeft = this.logDetailHTML.getBoundingClientRect().left
          let logDetailTop = this.logDetailHTML.getBoundingClientRect().top
          let x = event.clientX - logDetailLeft
          let y = event.clientY - logDetailTop

          if (y > this.logDetailHTML.clientHeight/2) {
            this.menuHTML.style.top = y - 30 + 'px'
          }
          else {
            this.menuHTML.style.top = y + 30 + 'px'
          }

          this.menuHTML.style.left = x + 10+ 'px'
          

          this.currentLogIndex = index
          this.isCurrentItemExpanded = this.currentLogDataArray[index].isExpanded
        },

        hideContextMenu(event) {
          if (this.menuHTML) {
            this.menuHTML.style.top = '-1000px'
          }
        },

        copyLog(index) {
          clipboard.copy(this.currentLogDataArray[index].message)
        },

        deleteLog(index) {
          let logType = this.currentLogDataArray[index].type
          this.currentLogDataArray.splice(index, 1)
          if (logType == 'log') {
            this.logNum -= 1
          }
          else if (logType == 'info') {
            this.infoNum -= 1
          }
          else if (logType == 'warn') {
            this.warnNum -= 1
          }
          else if (logType == 'error') {
            this.errorNum -= 1
          }
        },

        truncate(item) {
          // 截断
          // 若处于展开状态，则不截断
          if (item.isExpanded) {
              return item.message
          }

          // 若大于100个字符，则截断
          if (item.message.length > 100) {
              return item.message.substring(0, 100) + '...'
          }
          return item.message
        },

        clearLog() {
          // 清空当前显示的日志
          Editor.Ipc.sendToMain('console-pro:clear-log')

          this.currentLogDataArray = []
          this.previousLogDataArray = JSON.stringify([])

          this.logNum = 0
          this.infoNum = 0
          this.warnNum = 0
          this.errorNum = 0
        },

        openSettings() {
          // 进入到设置页面
          this.currentPage = 'settings'
        },

        openLog() {
          // 打开日志文件
          let logFilePath = path.join(os.homedir(), '.CocosCreator/logs/CocosCreator.log')
          if (fs.existsSync(logFilePath)) {
            if (os.type() == "Windows_NT") {
              childProcess.exec(`explorer.exe ${logFilePath}`)
            }
            else if (os.type() == "Darwin") {
              childProcess.exec(`open ${logFilePath}`)
            }
          }
          else {
            Editor.Dialog.messageBox({
              message: translate('noLogFile'),
              buttons: ['Ok'],
              title: 'Cocos Console Pro',
            })
          }
        },

        onMatchCaseBtnClicked() {
          // 当点击了大小写匹配按钮
          this.isMatchCase = !this.isMatchCase
          this.matchCaseBtnClass = this.isMatchCase ? 'blue transparent' : 'transparent'

          this.search(this.keyword)
        },

        onMatchWholeBtnClicked() {
          // 当点击了全字符匹配按钮
          this.isMatchWhole = !this.isMatchWhole
          this.matchWholeBtnClass = this.isMatchWhole ? 'blue transparent' : 'transparent'

          this.search(this.keyword)
        },

        onMatchRegBtnClicked() {
          // 当点击了正则匹配按钮
          this.isMatchReg = !this.isMatchReg
          this.matchRegBtnClass = this.isMatchReg ? 'blue transparent' : 'transparent'

          this.search(this.keyword)
        },

        showHideCertainTypeOfLog(logType) {
          // 当点击了右上角某个类型日志，可显示或隐藏对应类型的所有日志
          if (logType == 'log') {
              this.isLogTypeShown = !this.isLogTypeShown
              this.logNumImgPath = this.isLogTypeShown ? Editor.url('packages://console-pro/static/images/log-color.png') : Editor.url('packages://console-pro/static/images/log-gray.png')
              
              for (let i=0; i<this.currentLogDataArray.length; i++) {
                  if (this.currentLogDataArray[i]['type'] == 'log') {
                      this.currentLogDataArray[i]['isShown'] = this.isLogTypeShown
                  }
              }
          }
          else if (logType == 'info') {
              this.isInfoTypeShown = !this.isInfoTypeShown
              this.infoNumImgPath = this.isInfoTypeShown ? Editor.url('packages://console-pro/static/images/info-color.png') : Editor.url('packages://console-pro/static/images/info-gray.png')

              for (let i=0; i<this.currentLogDataArray.length; i++) {
                  if (this.currentLogDataArray[i]['type'] == 'info') {
                      this.currentLogDataArray[i]['isShown'] = this.isInfoTypeShown
                  }
              }
          }
          else if (logType == 'warn') {
              this.isWarnTypeShown = !this.isWarnTypeShown
              this.warnNumImgPath = this.isWarnTypeShown ? Editor.url('packages://console-pro/static/images/warn-color.png') : Editor.url('packages://console-pro/static/images/warn-gray.png')

              for (let i=0; i<this.currentLogDataArray.length; i++) {
                  if (this.currentLogDataArray[i]['type'] == 'warn') {
                      this.currentLogDataArray[i]['isShown'] = this.isWarnTypeShown
                  }
              }
          }
          else if (logType == 'error') {
              this.isErrorTypeShown = !this.isErrorTypeShown
              this.errorNumImgPath = this.isErrorTypeShown ? Editor.url('packages://console-pro/static/images/error-color.png') : Editor.url('packages://console-pro/static/images/error-gray.png')

              for (let i=0; i<this.currentLogDataArray.length; i++) {
                  if (this.currentLogDataArray[i]['type'] == 'error') {
                      this.currentLogDataArray[i]['isShown'] = this.isErrorTypeShown
                  }
              }
          }

          // 滑动条下滑
          this.$nextTick(()=>{
            if (this.isScrollAtBottom()) {
              this.logDetailHTML.scrollTop = Number.MAX_SAFE_INTEGER
            }
          })
        },

        expandLog(index) {
          // 展开日志
          this.currentLogDataArray[index].isExpanded = !this.currentLogDataArray[index].isExpanded
        },

        logTypeTologPath(logType) {
          // 将日志类型转换为日志图标
          return Editor.url(`packages://console-pro/static/images/${logType}-color.png`)
        },

        timeStampToDateTime(timestamp) {
          // 将时间戳转换为日期时间
          let date = new Date(timestamp)
          let year = date.getFullYear()
          let month = date.getMonth() + 1
          let day = date.getDate()
          let hour = date.getHours()
          let minute = date.getMinutes()
          let second = date.getSeconds()

          // 小于10的话，前面补齐'0'
          let monthStr = month < 10 ? '0'+month : month.toString()
          let dayStr = day < 10 ? '0'+day : day.toString()
          let hourStr = hour < 10 ? '0'+hour : hour.toString()
          let minuteStr = minute < 10 ? '0'+minute : minute.toString()
          let secondStr = second < 10 ? '0'+second : second.toString()

          return `${year}-${monthStr}-${dayStr} ${hourStr}:${minuteStr}:${secondStr}`
        },

        isScrollAtBottom() {
          // 判断滚动条是否在底部
          if (!this.logDetailHTML) {
            return false
          }

          let clientHeight = this.logDetailHTML.clientHeight
          let scrollTop = this.logDetailHTML.scrollTop
          let scrollHeight = this.logDetailHTML.scrollHeight
          if (clientHeight + scrollTop >= scrollHeight * 0.98) {
            return true
          }
          return false
        },

        updateLog(logType, msg) {
          let item = {
            'type': logType,
            'message': msg,
            'time': new Date().valueOf(),
            'isExpanded': false
          }

          if (logType == 'log') {
              this.logNum += 1
              item.isShown = this.isLogTypeShown
          }
          else if (logType == 'info') {
              this.infoNum += 1
              item.isShown = this.isInfoTypeShown
          }
          else if (logType == 'warn') {
              this.warnNum += 1
              item.isShown = this.isWarnTypeShown
          }
          else if (logType == 'error') {
              this.errorNum += 1
              item.isShown = this.isErrorTypeShown
          }

          this.currentLogDataArray.push(item)

          // 滑动条下滑
          this.$nextTick(()=>{
            if (this.isScrollAtBottom()) {
              this.logDetailHTML.scrollTop = Number.MAX_SAFE_INTEGER
            }
          })
        }
      }
    })
  },

  // register your ipc messages here
  messages: {
    'editor:console-log': (event, msg)=>{
      vm.updateLog('log', msg)
    },

    'editor:console-success': (event, msg)=>{
      vm.updateLog('log', msg)
    },

    'editor:console-failed': (event, msg)=>{
      vm.updateLog('error', msg)
    },

    'editor:console-info': (event, msg)=>{
      vm.updateLog('info', msg)
    },

    'editor:console-warn': (event, msg)=>{
      vm.updateLog('warn', msg)
    },

    'editor:console-error': (event, msg)=>{
      vm.updateLog('error', msg)
    },

    'scene:play-on-device': (event)=>{
      if (vm.isClearLogOnPreview) {
        vm.clearLog()
      }
    },
  }
});